/*
 * Copyright (c) 2020 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.diegocarloslima.fgelv.lib;

import com.diegocarloslima.fgelv.lib.util.ResUtil;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.BaseItemProvider;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.components.Text;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.media.image.PixelMap;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Image;

import java.util.HashMap;
import java.util.List;
import java.util.Optional;

import static ohos.agp.utils.LayoutAlignment.TOP;

public abstract class ExpandableListAdapter<T> extends BaseItemProvider {
    private Context context;
    private List<T> names;
    private List<Integer> images;
    private int mLayoutId;
    private OnItemClickListener onItemClickListener;

    /**
     * Constructor to get data from parent class
     *
     * @param context   context of view
     * @param mLayoutId resource layout to be drawn
     * @param names     group item name to be displayed
     * @param images    group item images to be displayed
     */
    protected ExpandableListAdapter(Context context, int mLayoutId, List<T> names, List<Integer> images) {
        this.context = context;
        this.names = names;
        this.images = images;
        this.mLayoutId = mLayoutId;
    }

    /**
     * This method is used to set updated data to the view
     *
     * @param data Updated data after collapse & expand the view
     */
    public void setData(List<T> data) {
        this.names = data;
        notifyDataChanged();
    }

    @Override
    public int getCount() {
        if (names != null) {
            return names.size();
        } else {
            return 0;
        }
    }

    @Override
    public T getItem(int position) {
        if (names != null) {
            return names.get(position);
        } else {
            return null;
        }
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public Component getComponent(int position, Component convertComponent, ComponentContainer parent) {
        ViewHolder viewHolder;
        convertComponent = new DirectionalLayout(context);
        ((DirectionalLayout) convertComponent).setOrientation(Component.HORIZONTAL);
        ComponentContainer.LayoutConfig layoutConfig = convertComponent.getLayoutConfig();
        layoutConfig.width = DependentLayout.LayoutConfig.MATCH_PARENT;
        layoutConfig.height = DependentLayout.LayoutConfig.MATCH_CONTENT;
        convertComponent.setLayoutConfig(layoutConfig);

        DirectionalLayout dlItemParent = new DirectionalLayout(context);
        dlItemParent.setLayoutConfig(new DirectionalLayout.LayoutConfig(0, DirectionalLayout.LayoutConfig.MATCH_CONTENT, TOP, 1));
        Component childConvertComponent = LayoutScatter.getInstance(context).parse(mLayoutId, null, false);

        childConvertComponent.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                if (onItemClickListener != null) {
                    onItemClickListener.onItemClick(component, position);
                }
            }
        });
        dlItemParent.addComponent(childConvertComponent);
        ((ComponentContainer) convertComponent).addComponent(dlItemParent);
        viewHolder = new ViewHolder(childConvertComponent);
        bind(viewHolder, getItem(position), images.get(position), position);

        return convertComponent;
    }

    /**
     * This method is used to provide item click listener
     *
     * @param onItemClickListener object of our interface
     */
    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    protected abstract void bind(ViewHolder holder, T s, Integer image, int position);

    protected static class ViewHolder {
        HashMap<Integer, Component> mViews = new HashMap<>();
        Component itemView;

        ViewHolder(Component component) {
            this.itemView = component;
        }

        /**
         * This method is used to set text of the group & child items
         *
         * @param viewId   resource id of text
         * @param text     string value to be displayed for group & child item
         * @param color    text color for group& child item
         * @param textSize text size for group& child item
         */
        public void setText(int viewId, String text, Color color, int textSize) {
            Text tvName = getView(viewId);
            tvName.setText(text);
            tvName.setTextColor(color);
            tvName.setTextSize(textSize);
        }

        /**
         * This method is used to set image for group items
         *
         * @param viewId     view id if image
         * @param imageResId image resource id to be displayed in image
         * @param shape      background shape for image
         * @param scaleMode  scale mode set on image
         * @param groupImageColor
         */
        public void setGroupImage(int viewId, Integer imageResId, int shape, Image.ScaleMode scaleMode, int groupImageColor) {
            Image imageView = getView(viewId);
            ShapeElement shapeElement = new ShapeElement();
            shapeElement.setRgbColor(RgbColor.fromArgbInt(ResUtil.getColor(imageView.getContext(),groupImageColor)));
            shapeElement.setShape(shape);
            imageView.setBackground(shapeElement);
            Optional<PixelMap> groupIconPixelMap = ResUtil.getPixelMap(imageView.getContext(), imageResId);
            groupIconPixelMap.ifPresent(imageView::setPixelMap);
            imageView.setScaleMode(scaleMode);
        }

        /**
         * This method is used to set child item image
         *
         * @param viewId     view id for image
         * @param imageRedId image resource id to be set on image
         * @param height
         * @param margin
         * @param width
         */
        public void setChildImage(int viewId, Integer imageRedId, int width, int height, int margin) {
            Image imageView = getView(viewId);
            imageView.setWidth(ResUtil.getIntDimen(itemView.getContext(), width));
            imageView.setHeight(ResUtil.getIntDimen(itemView.getContext(), height));
            imageView.setMarginLeft(ResUtil.getIntDimen(itemView.getContext(), margin));
            Optional<PixelMap> groupIconPixelMap = ResUtil.getPixelMap(imageView.getContext(), imageRedId);
            groupIconPixelMap.ifPresent(imageView::setPixelMap);
            imageView.setScaleMode(Image.ScaleMode.STRETCH);
        }

        /**
         * This method is used to set background of group items
         * @param groupItemColor
         * @param groupItemLayoutId
         */
        public void setGroupItemBackground(int groupItemLayoutId, int groupItemColor) {
            DependentLayout groupContainer = (DependentLayout) itemView.findComponentById(groupItemLayoutId);
            ShapeElement containerElement = new ShapeElement();
            containerElement.setShape(ShapeElement.RECTANGLE);
            containerElement.setRgbColor(RgbColor.fromArgbInt(ResUtil.getColor(groupContainer.getContext(), groupItemColor)));
            groupContainer.setBackground(containerElement);
        }

        /**
         * This method is used to set background of group items
         * @param color
         * @param dividerId
         */
        public void setGroupItemDivider(int dividerId, int color) {
            DirectionalLayout childDivider = (DirectionalLayout) itemView.findComponentById(dividerId);
            ShapeElement dividerElement = new ShapeElement();
            dividerElement.setShape(ShapeElement.RECTANGLE);
            dividerElement.setRgbColor(RgbColor.fromArgbInt(color));
            childDivider.setBackground(dividerElement);
        }

        /**
         * This method will return the view based on id
         *
         * @param viewId view id of component
         * @param <E>    component to be return based on id
         * @return component
         */
        <E extends Component> E getView(int viewId) {
            E view = (E) mViews.get(viewId);
            if (view == null) {
                view = (E) itemView.findComponentById(viewId);
                mViews.put(viewId, view);
            }
            return view;
        }
    }

    public static abstract class OnItemClickListener {
        public abstract void onItemClick(Component component, int position);
    }
}
